package xiongwei.jiang.service;

import org.springframework.web.bind.annotation.RequestBody;
import xiongwei.jiang.constant.enums.CheckinType;
import xiongwei.jiang.constant.enums.State;
import xiongwei.jiang.constant.enums.UploadTempType;
import xiongwei.jiang.constant.enums.WXWorkApiType;
import xiongwei.jiang.model.dto.request.MarkdownAppMsg;
import xiongwei.jiang.model.dto.request.MarkdownBotMsg;
import xiongwei.jiang.model.dto.request.TextAppMsg;
import xiongwei.jiang.model.dto.request.TextBotMsg;
import xiongwei.jiang.model.dto.response.*;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 企业微信服务接口
 *
 * @author 天之蓝
 */
public interface WXWorkService {
    /**
     * 企业内部开发 / 服务端API / 开发指南 / 获取access_token
     *
     * @param type   {@link WXWorkApiType}
     * @param name   名称
     * @param corpId 客户端编号
     * @param secret 客户端密钥
     * @return 令牌
     * @author 天之蓝
     */
    String getToken(WXWorkApiType type, String name, String corpId, String secret);

    /**
     * 企业内部开发 / 服务端API / 开发指南 / 获取access_token
     *
     * @param type   {@link WXWorkApiType}
     * @param name   名称
     * @param corpId 客户端编号
     * @param secret 客户端密钥
     * @return 令牌
     * @author 天之蓝
     * @see #getToken(WXWorkApiType, String, String, String)
     */
    String getTokenCache(WXWorkApiType type, String name, String corpId, String secret);

    /**
     * 企业内部开发 / 服务端API / 开发指南 / 回调配置 / 支持Http Get请求验证URL有效性
     *
     * @param name          名称
     * @param msg_signature 企业微信加密签名，msg_signature计算结合了企业填写的token、请求中的timestamp、nonce、加密的消息体
     * @param timestamp     时间戳（与nonce结合使用，用于防止请求重放攻击）
     * @param nonce         随机数（与timestamp结合使用，用于防止请求重放攻击）
     * @param echostr       加密的字符串（需要解密得到消息内容明文，解密后有random、msg_len、msg、receiveid四个字段，其中msg即为消息内容明文）
     * @param response      响应
     * @author 天之蓝
     */
    void verifyUrl(String name, String msg_signature, String timestamp, String nonce, String echostr, HttpServletResponse response);

    /**
     * 企业内部开发 / 服务端API / 开发指南 / 回调配置 / 支持Http Post请求接收业务数据
     *
     * @param name          名称
     * @param msg_signature 企业微信加密签名，msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体
     * @param timestamp     时间戳（与nonce结合使用，用于防止请求重放攻击）
     * @param nonce         随机数（与timestamp结合使用，用于防止请求重放攻击）
     * @param xml           回调数据（放在 HTTP 请求体中，使用注解 {@link RequestBody} 接收）
     * @param response      响应
     * @return {@link Map}
     * @author 天之蓝
     */
    Map<String, Object> callback(String name, String msg_signature, String timestamp, String nonce, String xml, HttpServletResponse response);

    /**
     * 企业内部开发 / 服务端API / 通讯录管理 / 成员管理 / 读取成员
     *
     * @param type   {@link WXWorkApiType}，可选 {@link WXWorkApiType#CONTACT} 和 {@link WXWorkApiType#APP}
     * @param name   名称
     * @param userId 工号
     * @return {@link UserInfo}
     * @author 天之蓝
     */
    UserInfo getUserInfo(WXWorkApiType type, String name, String userId);

    /**
     * 企业内部开发 / 服务端API / 通讯录管理 / 成员管理 / 获取部门成员
     *
     * @param type         {@link WXWorkApiType}，可选 {@link WXWorkApiType#CONTACT} 和 {@link WXWorkApiType#APP}
     * @param name         名称
     * @param departmentId 部门 id
     * @param fetchChild   是否递归获取子部门下面的成员（1-递归获取，0-只获取本部门）
     * @return {@link DepartmentUser}
     * @author 天之蓝
     */
    DepartmentUser getDepartmentUser(WXWorkApiType type, String name, int departmentId, State fetchChild);

    /**
     * 企业内部开发 / 服务端API / 通讯录管理 / 部门管理 / 获取部门列表
     *
     * @param type         {@link WXWorkApiType}，可选 {@link WXWorkApiType#CONTACT} 和 {@link WXWorkApiType#APP}
     * @param name         名称
     * @param departmentId 部门 id，获取指定部门及其下的子部门（以及子部门的子部门等等，递归）；如果不填，默认获取全量组织架构
     * @return {@link DepartmentList}
     * @author 天之蓝
     */
    DepartmentList getDepartmentList(WXWorkApiType type, String name, int departmentId);

    /**
     * 企业内部开发 / 服务端API / 通讯录管理 / 标签管理 / 获取标签成员
     *
     * @param type  {@link WXWorkApiType}，可选 {@link WXWorkApiType#CONTACT} 和 {@link WXWorkApiType#APP}
     * @param name  名称
     * @param tagId 标签 id
     * @return {@link TagUser}
     * @author 天之蓝
     */
    TagUser getTagUser(WXWorkApiType type, String name, int tagId);

    /**
     * 企业内部开发 / 服务端API / 通讯录管理 / 标签管理 / 获取标签列表
     *
     * @param type {@link WXWorkApiType}，可选 {@link WXWorkApiType#CONTACT} 和 {@link WXWorkApiType#APP}
     * @param name 名称
     * @return {@link TagList}
     * @author 天之蓝
     */
    TagList getTagList(WXWorkApiType type, String name);

    /**
     * 企业内部开发 / 服务端API / 身份验证 / 网页授权登录 / 获取访问用户身份
     *
     * @param name 名称
     * @param code 企业微信授权码，仅可使用一次，5 分钟内有效
     * @return {@link User}
     * @author 天之蓝
     */
    User getUser(String name, String code);

    /**
     * 企业内部开发 / 服务端API / 消息推送 / 发送应用消息 / 文本消息
     *
     * @param name   名称
     * @param object {@link TextAppMsg}
     * @return {@link AppMsg}
     * @author 天之蓝
     */
    AppMsg sendAppTextMsg(String name, TextAppMsg object);

    /**
     * 企业内部开发 / 服务端API / 消息推送 / 发送应用消息 / markdown消息
     *
     * @param name   名称
     * @param object {@link MarkdownAppMsg}
     * @return {@link AppMsg}
     * @author 天之蓝
     */
    AppMsg sendAppMarkdownMsg(String name, MarkdownAppMsg object);

    /**
     * 企业内部开发 / 服务端API / 素材管理 / 上传临时素材
     *
     * @param name     名称
     * @param tempType {@link UploadTempType}
     * @param filePath 临时素材绝对路径
     * @return {@link UploadTemp}
     * @author 天之蓝
     */
    UploadTemp uploadTemp(String name, UploadTempType tempType, String filePath);

    /**
     * 企业内部开发 / 服务端API / 素材管理 / 上传图片
     *
     * @param name     名称
     * @param filePath 图片绝对路径
     * @return {@link UploadImage}
     * @author 天之蓝
     */
    UploadImage uploadImage(String name, String filePath);

    /**
     * 企业内部开发 / 服务端API / 素材管理 / 获取临时素材
     *
     * @param name    名称
     * @param mediaId 媒体文件 id
     * @return 字节数组
     * @author 天之蓝
     */
    byte[] downloadTemp(String name, String mediaId);

    /**
     * 企业内部开发 / 服务端API / 素材管理 / 获取高清语音素材
     *
     * @param name    名称
     * @param mediaId 媒体文件 id
     * @return 字节数组
     * @author 天之蓝
     */
    byte[] downloadVoice(String name, String mediaId);

    /**
     * 企业内部开发 / 服务端API / OA / 打卡 / 获取打卡记录数据
     *
     * @param name                名称
     * @param openCheckinDataType 打卡类型（1-上下班打卡，2-外出打卡，3-全部打卡）
     * @param startTime           获取打卡记录的开始时间（10 位 Unix 时间戳）
     * @param endTime             获取打卡记录的结束时间（10 位 Unix 时间戳）
     * @param userIdList          工号集合（至多 100 个）
     * @return {@link CheckinRecord}
     * @author 天之蓝
     */
    CheckinRecord getCheckinRecord(String name, CheckinType openCheckinDataType, long startTime, long endTime, List<String> userIdList);

    /**
     * 企业内部开发 / 客户端API / JS-SDK / 附录 / JS-SDK使用权限签名算法 / 获取企业的jsapi_ticket
     *
     * @param name 名称
     * @return 企业凭证
     * @author 天之蓝
     */
    String getCorpTicket(String name);

    /**
     * 企业内部开发 / 客户端API / JS-SDK / 附录 / JS-SDK使用权限签名算法 / 获取企业的jsapi_ticket
     *
     * @param name 名称
     * @return 企业凭证
     * @author 天之蓝
     * @see #getCorpTicket(String)
     */
    String getCorpTicketCache(String name);

    /**
     * 企业内部开发 / 客户端API / JS-SDK / 附录 / JS-SDK使用权限签名算法 / 获取应用的jsapi_ticket
     *
     * @param name 名称
     * @return 应用凭证
     * @author 天之蓝
     */
    String getAppTicket(String name);

    /**
     * 企业内部开发 / 客户端API / JS-SDK / 附录 / JS-SDK使用权限签名算法 / 获取应用的jsapi_ticket
     *
     * @param name 名称
     * @return 应用凭证
     * @author 天之蓝
     * @see #getAppTicket(String)
     */
    String getAppTicketCache(String name);

    /**
     * 企业内部开发 / 客户端API / JS-SDK / 开始开发 / 使用说明 / 通过config接口注入权限验证配置
     *
     * @param name   名称
     * @param webUrl {@code window.location.href}
     * @return {@link Map}
     * @author 天之蓝
     */
    Map<String, Object> getCorpConfig(String name, String webUrl);

    /**
     * 企业内部开发 / 客户端API / JS-SDK / 基础接口 / wx.agentConfig / 通过agentConfig注入应用的权限
     *
     * @param name   名称
     * @param webUrl {@code window.location.href}
     * @return {@link Map}
     * @author 天之蓝
     */
    Map<String, Object> getAppConfig(String name, String webUrl);

    /**
     * 企业内部开发 / 客户端API / 群机器人 / 群机器人配置说明 / 文本类型
     *
     * @param name   名称
     * @param object {@link TextBotMsg}
     * @return {@link Result}
     * @author 天之蓝
     */
    Result sendBotTextMsg(String name, TextBotMsg object);

    /**
     * 企业内部开发 / 客户端API / 群机器人 / 群机器人配置说明 / markdown类型
     *
     * @param name   名称
     * @param object {@link MarkdownBotMsg}
     * @return {@link Result}
     * @author 天之蓝
     */
    Result sendBotMarkdownMsg(String name, MarkdownBotMsg object);
}
